Skip to content

Conversation

@itingliu
Copy link
Contributor

@itingliu itingliu commented Jun 2, 2025

Previously we maintain a cache private var cachedFixedComponentsLocales: [Locale.Components : any _LocaleProtocol], and every call to Locale(components: Locale.Components) reads a
nd writes to the cache. This results in a cache with non trivial size of keys.

Optimize this by replacing the key with a String instead of the full Locale.Components instance.

Using this as the baseline:

for identifier in Locale.availableIdentifiers {
    let locale = Locale(identifier: identifier)
}

With the following as the testing code:

for identifier in Locale.availableIdentifiers {
    let components = Locale.Components(identifier: identifier)
    let locale = Locale(components: components)
    let components2 = Locale.Components(locale: locale)
    let locale2 = Locale(components: components2) // cache hit
}

Previously, this incurred +2.6 MB of footprint comparing to the above baseline. After the fix, it incurred only +0.9MB increase.

Also benchmarked that we have not regressed the time now that we are using the string-based identifier as the key.

itingliu added 2 commits June 2, 2025 15:48
Previously we maintain a cache `private var cachedFixedComponentsLocales: [Locale.Components : any _LocaleProtocol]`, and every call to `Locale(components: Locale.Components)` reads and writes to the cache. This results in a cache with non trivial size of keys.

Optimize this by replacing the key with a String instead of the full `Locale.Components` instance.

Using this as the baseline:

```swift
for identifier in Locale.availableIdentifiers {
    let locale = Locale(identifier: identifier)
}
```

With the following as the testing code:

```swift
for identifier in Locale.availableIdentifiers {
    let components = Locale.Components(identifier: identifier)
    let locale = Locale(components: components)
    let components2 = Locale.Components(locale: locale)
    let locale2 = Locale(components: components2) // cache hit
}
```

Previously, this incurred +2.6 MB of footprint comparing to the above baseline. After the fix, it incurred only +0.9MB increase.

Also benchmarked that we have not regressed the time now that we are using the string-based identifier as the key.

Fixes 144642686
@itingliu
Copy link
Contributor Author

itingliu commented Jun 2, 2025

@swift-ci please test

@itingliu itingliu requested a review from parkera June 3, 2025 18:15
@itingliu itingliu merged commit 1e9a609 into swiftlang:main Jun 4, 2025
15 checks passed
@itingliu itingliu deleted the pr/3162 branch June 4, 2025 21:01
chloe-yeo pushed a commit to chloe-yeo/swift-foundation that referenced this pull request Jun 10, 2025
* Reduce size of `cachedFixedComponentsLocales`

Previously we maintain a cache `private var cachedFixedComponentsLocales: [Locale.Components : any _LocaleProtocol]`, and every call to `Locale(components: Locale.Components)` reads and writes to the cache. This results in a cache with non trivial size of keys.

Optimize this by replacing the key with a String instead of the full `Locale.Components` instance.

Using this as the baseline:

```swift
for identifier in Locale.availableIdentifiers {
    let locale = Locale(identifier: identifier)
}
```

With the following as the testing code:

```swift
for identifier in Locale.availableIdentifiers {
    let components = Locale.Components(identifier: identifier)
    let locale = Locale(components: components)
    let components2 = Locale.Components(locale: locale)
    let locale2 = Locale(components: components2) // cache hit
}
```

Previously, this incurred +2.6 MB of footprint comparing to the above baseline. After the fix, it incurred only +0.9MB increase.

Also benchmarked that we have not regressed the time now that we are using the string-based identifier as the key.

Fixes 144642686

* Add a comment about using Locale.Components.icuIdentifier as the cache key
chloe-yeo pushed a commit to chloe-yeo/swift-foundation that referenced this pull request Jun 16, 2025
* Reduce size of `cachedFixedComponentsLocales`

Previously we maintain a cache `private var cachedFixedComponentsLocales: [Locale.Components : any _LocaleProtocol]`, and every call to `Locale(components: Locale.Components)` reads and writes to the cache. This results in a cache with non trivial size of keys.

Optimize this by replacing the key with a String instead of the full `Locale.Components` instance.

Using this as the baseline:

```swift
for identifier in Locale.availableIdentifiers {
    let locale = Locale(identifier: identifier)
}
```

With the following as the testing code:

```swift
for identifier in Locale.availableIdentifiers {
    let components = Locale.Components(identifier: identifier)
    let locale = Locale(components: components)
    let components2 = Locale.Components(locale: locale)
    let locale2 = Locale(components: components2) // cache hit
}
```

Previously, this incurred +2.6 MB of footprint comparing to the above baseline. After the fix, it incurred only +0.9MB increase.

Also benchmarked that we have not regressed the time now that we are using the string-based identifier as the key.

Fixes 144642686

* Add a comment about using Locale.Components.icuIdentifier as the cache key
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants